package com.gm.wj.service;

import com.gm.wj.dao.UserDAO;
import com.gm.wj.dto.UserDTO;
import com.gm.wj.entity.AdminRole;
import com.gm.wj.entity.SysStudent;
import com.gm.wj.entity.SysTeacher;
import com.gm.wj.entity.User;
import com.gm.wj.util.VerifyUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.util.HtmlUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Evan
 * @date 2019/4
 */
@Slf4j
@Service
public class UserService {
    @Autowired
    UserDAO userDAO;
    @Autowired
    AdminRoleService adminRoleService;
    @Autowired
    AdminUserRoleService adminUserRoleService;

    public List<UserDTO> list() {
        List<User> users = userDAO.findAll();

        // 在数据库中查找所有角色以启用JPA持久性上下文。
        // List<AdminRole> allRoles = adminRoleService.findAll();

        return getUserDTOS(users);
    }


    public boolean isExist(String username) {
        User user = userDAO.findByUsername(username);
        return null != user;
    }

    public User findByUsername(String username) {
        return userDAO.findByUsername(username);
    }

    public User get(String username, String password) {
        return userDAO.getByUsernameAndPassword(username, password);
    }

    public int registerStu(SysStudent sysStudent) {
        User user = new User();
        user.setUsername(sysStudent.getUsername());
        user.setPassword("0774123");
        user.setPhone(sysStudent.getPhone());
        user.setName(sysStudent.getStuName());
        user.setEmail(sysStudent.getEmail());
        user.setIdentity(1); // 0-管理员；1-学生；2-老师
        return register(user);
    }

    public int registerTea(SysTeacher sysTeacher) {
        User user = new User();
        user.setUsername(sysTeacher.getUsername());
        user.setPassword("0774123");
        user.setPhone(sysTeacher.getPhone());
        user.setName(sysTeacher.getTeaName());
        user.setEmail(sysTeacher.getEmail());
        user.setIdentity(2); // 0-管理员；1-学生；2-老师
        return register(user);
    }

    public int register(User user) {
        String username = user.getUsername();
        String name = user.getName();
        String phone = user.getPhone();
        String email = user.getEmail();
        String password = user.getPassword();

        username = HtmlUtils.htmlEscape(username);
        user.setUsername(username);
        name = HtmlUtils.htmlEscape(name);
        user.setName(name);
        phone = HtmlUtils.htmlEscape(phone);
        user.setPhone(phone);
        email = HtmlUtils.htmlEscape(email);
        user.setEmail(email);
        user.setEnabled(true);

        if (username.equals("") || password.equals("")) {
            return 0;
        }

        boolean exist = isExist(username);

        if (exist) {
            return 2;
        }

        // 默认生成 16 位盐
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        int times = 2;
        String encodedPassword = new SimpleHash("md5", password, salt, times).toString();

        user.setSalt(salt);
        user.setPassword(encodedPassword);

        userDAO.save(user);

        return 1;
    }

    public void updateUserStatus(User user) {
        User userInDB = userDAO.findByUsername(user.getUsername());
        userInDB.setEnabled(user.isEnabled());
        userDAO.save(userInDB);
    }

    public User resetPassword(User user) {
        User userInDB = userDAO.findByUsername(user.getUsername());
        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        int times = 2;
        userInDB.setSalt(salt);
        String encodedPassword = new SimpleHash("md5", "0774123", salt, times).toString();
        userInDB.setPassword(encodedPassword);
        return userDAO.save(userInDB);
    }

    public void editUser(User user) {
        User userInDB = userDAO.findByUsername(user.getUsername());
        userInDB.setName(user.getName());
        userInDB.setPhone(user.getPhone());
        userInDB.setEmail(user.getEmail());
        userDAO.save(userInDB);
        adminUserRoleService.saveRoleChanges(userInDB.getId(), user.getRoles());
    }

    public void deleteById(int id) {
        userDAO.deleteById(id);
    }

    public List<UserDTO> listUsersByQueryKey(String queryKey1, String queryKey2, String queryKey3) {

        // 多条件模糊查询
        queryKey1 = (queryKey1 == null) ? null : "%" + queryKey1 + "%";
        queryKey2 = (queryKey2 == null) ? null : "%" + queryKey2 + "%";
        queryKey3 = (queryKey3 == null) ? null : "%" + queryKey3 + "%";
        List<User> users = userDAO.find(queryKey1, queryKey2, queryKey3);

        return getUserDTOS(users);

    }

    private List<UserDTO> getUserDTOS(List<User> users) {
        // users查询所有用户信息，逐一赋值给DTO
        List<UserDTO> userDTOS = users
                .stream().map(user -> (UserDTO) new UserDTO().convertFrom(user)).collect(Collectors.toList());
        // DTO代理u，根据username逐个查询赋值roles
        userDTOS.forEach(u -> {
            List<AdminRole> roles = adminRoleService.listRolesByUser(u.getUsername());
            u.setRoles(roles);
        });
        return userDTOS;
    }

    // 查询个人信息
    public List<UserDTO> usersByUsername() {
        String username = SecurityUtils.getSubject().getPrincipal().toString();
        List<User> users = userDAO.findAllByUsername(username);
        // users查询所有用户信息，逐一赋值给DTO
        List<UserDTO> userDTOS = users
                .stream().map(user -> (UserDTO) new UserDTO().convertFrom(user)).collect(Collectors.toList());
        return userDTOS;
    }

    public int findUserData() {
        return userDAO.countByUser();
    }

    /**
     * 数据效验
     * @param user
     * @return
     */
    public int verifyCode(User user) {
            if (!VerifyUtils.isEmail(user.getEmail())) {
                return 0; // 效验邮箱错误
            }
            if (!VerifyUtils.isMobileNO(user.getPhone())) {
                return 2;  // 效验手机错误
            }
            return 1;
    }

}
